import { reactive, toRefs, computed } from "vue"
import { onShow, onUnload, onReady, onLoad, onHide } from "@dcloudio/uni-app";
import { generate28DigitOrderId } from "@/utils/index.js"
import { LoginStore } from "@/store/modules/login";
import { ConfigStore } from "@/store/modules/config.js"
const createAllPayApi = uniCloud.importObject('qc-pay', { customUI: true })
/**
 * @description  接受邀请
 * @param rules 表单校验规则
 * */
export const usePay = (payRef, payPopup, props) => {
	const LoginState = LoginStore()
	const state = reactive({
		vkPay: {
			/**
			 * 查询支付状态的云函数配置
			 * 如果是非路由框架，则action为字符串，值为云函数名称
			 * 如果是路由框架，则按下方配置填写
			 * 注意：queryPaymentAction内参数用默认即可，无需更改。（除非你已经知道参数的意义）
			 */
			queryPaymentAction: {
				name: "vk-pay", // 云函数名称
				action: "pay/queryPayment", // 路由模式下云函数地址
				actionKey: "action", // 路由模式下云函数地址的识别key
				dataKey: "data" // 路由模式下云函数请求参数的识别key
			},
			// PC支付的付款二维码地址，渲染二维码需要自己写，可以参考示例中的二维码组件 vk-uni-qrcode
			codeUrl: "",
			qrcodeImage: "",
			// 当前支付状态 0:等待发起支付 1:支付中 2:已支付（注意：跟数据库的status无关）
			status: 0,
			// 当前页面是否显示
			pageShow: true,
			// 启用轮询检测订单支付状态（仅h5支付有效）
			polling: true,
			// 仅微信手机外部浏览器H5支付时有效，必须是http或https开头的绝对路径，且在微信H5支付配置的域名白名单中。你还需要将此H5域名加入uniCloud白名单
			// 如果此值为空，则默认返回当前页面，返回的页面url参数会带上confirmShow=true&out_trade_no=实际订单号
			returnUrl: "",
			// 确认已支付的弹窗开关（微信手机外部浏览器H5支付时有效）
			confirmShow: false,
			// 支付成功后，是否需要等待异步回调全部执行完成后才通知前端（当awaitNotify和payOrderInfo均为false时，支付成功的响应速度最快）
			awaitNotify: true,
			// 支付成功后，是否需要返回支付订单数据（当awaitNotify和payOrderInfo均为false时，支付成功的响应速度最快）
			payOrderInfo: false,
			// 是否自动获取小程序的openid（若传false，则在createPayment时需要自己传对应的openid，一般服务商模式下需要传false）
			autoGetOpenid: true,
		},
		// 支付参数
		options: {},
		images: {
			wxpay: "../../../static/image/pay/wx.png",
			alipay: "../../../static/image/pay/zfb.png",
			coupon: "../../../static/image/pay/qb.png",
			topup_balance: "../../../static/image/pay/ye.png",
			kefu: "../../../static/image/my/kf.png"
		},
		originalRroviders: ["wxpay", "alipay", 'paykl', 'payQR', 'auto_payQR', 'auto_wxQR','polymer_pay','payYhk'], //支付场景
		currentProviders: ["wxpay", "alipay"], //支付渠道
		userInfo: {},
		refreshNum: 0, //刷新卡数量
		stickyNum: 0, //这个置顶卡
		loading: false
	})

	// 获取用户信息
	const userInfo = computed(() => (LoginStore().userInfo))
	// 获取全局配置项
	const config = computed(() => (ConfigStore().config))
	// 主页面使用
	onLoad((options = {}) => {
		state.userInfo = userInfo.value
		// 此处是因为微信H5外部浏览器支付后微信会重新打开指定页面，我们需要做一个弹窗让用户自己点下是否支付成功，同时云函数会去请求微信服务器检查是否真的付款成功。
		state.vkPay.confirmShow = options.confirmShow || false;
		if (options.out_trade_no) state.options.out_trade_no = options.out_trade_no;
		if (options.code && options.state) {
			// 获取微信公众号的openid
			setTimeout(() => {
				getOpenid({
					code: options.code
				});
			}, 300);
		}
	})
	// 监听 - 页面每次【显示时】执行(如：前进和返回) (页面每次出现在屏幕上都触发，包括从下级页面点返回露出当前页面)
	onShow(() => {
		state.vkPay.pageShow = true;
	})
	// 监听 - 页面每次【隐藏时】执行(如：返回)
	onHide(() => {
		state.vkPay.pageShow = false;
	})

	// 发起支付 - 打开支付选项弹窗
	const open = async (options = {}) => {
		// 如果有支付类型，说明用户是充值，不进行更新用户信息
		if (!options.data.provider) {
			LoginStore().updateUserInfo()
		}
		// 是否指定支付服务商 如 wxpay | alipay
		if (options.data.provider) {
			let providers = [];
			// 如果支付渠道中有传入的服务商 就添加到providers
			state.originalRroviders.map((item, index) => {
				// if (options.data.provider.indexOf(item) > -1) {
				// 	providers.push(item);
				// }
				if (options.data.provider == item) {
					providers.push(item);
				}
			});
			// 赋值给渠道支付场景currentProviders
			state.currentProviders = providers;
		
			delete options.data.provider;
		} else {
			// 如果没有传要指定的支付方式 就使用后端控制请求的数据
			if (options.data.type == 'vip') {
				state.currentProviders = config.value.vipPayTypes
			} else {
				state.currentProviders = config.value.adPayTypes
			}
			// 前端控制
			// if (options.data.isPay) {
			// 	// 如果没有传 默认就使用 zfb wx
			// 	state.currentProviders = JSON.parse(JSON.stringify(state.originalRroviders));
			// } else {
			// 	// 如果没有传 默认就使用 充值余额 收入余额 卡包
			// 	state.currentProviders = Array.isArray(props.payWay) ? props.payWay : [props.payWay]
			// }

		}
		// 把传递的支付数据 进行保存
		state.options = Object.assign(state.options, options.data, options);
		// 如果支付渠道中有数据就创建支付
		if (state?.currentProviders?.length === 1) {
			if (state?.currentProviders.includes('income_balance') || state?.currentProviders?.includes('topup_balance') || state?.currentProviders.includes('coupon')) {
			//内部支付	
				createAccount({ provider: state.currentProviders[0] })
			} else {
			//三方支付
				createPayment({ provider: state.currentProviders[0] });
			}
		} else {
			// 打开弹窗
			openPopup("payPopup");
		}
	}

	// 打开弹窗
	const openPopup = (name) => {
		state.userInfo = userInfo.value
		payPopup.value.open();
		// 查选刷新卡数量
		const filteredCoupons = userInfo?.value?.money?.coupon?.filter(coupon => coupon.couponType === 1);
		const filteredSticky = userInfo?.value?.money?.coupon?.filter(coupon => coupon.couponType === 0);
		state.refreshNum = filteredCoupons?.reduce((acc, curr) => acc + curr.couponNum, 0)
		state.stickyNum = filteredSticky?.reduce((acc, curr) => acc + curr.couponNum, 0)
	}
	// 关闭弹窗
	const closePopup = (name) => {
		payPopup.value.close();
	}
	// 取消支付
	const cancelPay = () => {
		state.vkPay.status = 0;
		state.vkPay.codeUrl = "";
		closePopup()
	}

	// 发起内部支付（）
	let isPaymentProcessing = false;
	const debouncedCreateAccount = async (obj = {}) => {
		if (isPaymentProcessing) {
			return;
		}
		isPaymentProcessing = true;
		let { options } = state;
		Object.assign(options, obj);
		try {
			state.loading = true
			const res = await createAllPayApi.createAllPay({
				provider: options.provider, //支付方式
				total_fee: options.total_fee, //支付金额
				subject: options.subject, //支付说明
				user_id: userInfo.value._id, //用户id
				type: options.type, //订单类型
				out_trade_no: generate28DigitOrderId(),
				custom: options.custom //预留字段（自定义的，可以传一些需要的参数在回调中使用）
			})
			closePopup()
			LoginStore().updateUserInfo()
			uni.showToast({ title: "支付成功", icon: "success", mask: true });
			state.loading = false
			options.onSuccess(res)
		} catch (e) {
			state.loading = false
			options.onFail(e);
			closePopup()
		} finally {
			state.loading = false
			// 无论支付成功还是失败，都要将 isPaymentProcessing 设置为 false 表示支付结束
			setTimeout(() => {
				isPaymentProcessing = false;
			}, 2000)
		}
	}

	// 防抖函数
	const debounce = (func, delay) => {
		let timer;
		return function(...args) {
			clearTimeout(timer);
			timer = setTimeout(() => {
				func.apply(this, args);
			}, delay);
		};
	}

	const createAccount = debounce(async function(...args) {
		await debouncedCreateAccount.apply(this, args);
	}, 1000);

	/* 
		type类型
		ad：'广告发布'
		recharge：'充值'
		vip：'开通会员'
		goods:'置顶，刷新，头条。。。。'
	 */



	// 口量红包，扫码支付（聚合），银行卡逻辑
	let isPayment = false;
	const createPay = async (options) => {
		if (isPayment) {
			return;
		}
		isPayment = true;
		const platform = uni.getSystemInfoSync()
		try {
			state.loading = true
			const res = await createAllPayApi.createPay({
				pay_type: options.provider, //支付方式 *
				status: 1, //支付状态
				type: options.type, //订单类型
				out_trade_no: options.out_trade_no, //商户订单号（需控制唯一）
				transaction_id: options.transaction_id, //交易单号 (支付平台订单号，由支付平台控制唯一) *扫码必填
				user_id: userInfo.value._id, //用户id 
				device_id: platform.device, //客户端设备ID
				platform: platform.uniPlatform, //设备应用
				description: options.subject, //支付描述，如：xxxx手机1台  *
				total_fee: options.total_fee, //订单总金额，单位为分，100等于1元 *
				create_date: Date.now(), //创建时间 
				pay_date: Date.now(), //支付时间
				payType: options.provider == 'paykl' ? 'alipay' : options.payType, //扫码支付类型
				command: options.command, //红包口令
				name: options.name, //姓名
				interior: true //是否为内部支付
			})
			state.loading = false
			uni.showToast({ title: "支付成功", icon: "success", mask: true });
			closePopup()
			options.onSuccess(res)
		} catch (e) {
			state.loading = false
			closePopup()
			options.onFail(e);
		} finally {
			// 无论支付成功还是失败，都要将 isPaymentProcessing 设置为 false 表示支付结束
			setTimeout(() => {
				isPayment = false;
			}, 2000)
		}
	}

	const createPays = debounce(createPay, 1000);


	// 码支付，自动识别微信，支付宝二维码支付
	let isAutoPayment = false;
	const createAutoPay = async (options) => {
		if (isAutoPayment) {
			return;
		}
		isAutoPayment = true;
		const platform = uni.getSystemInfoSync()
		try {
			state.loading = true
			const res = await createAllPayApi.createAutoPay({
				pay_type: options.provider, //支付方式 *
				status: 0, //支付状态
				type: options.type, //订单类型
				out_trade_no: options.out_trade_no, //商户订单号（需控制唯一）
				user_id: userInfo?.value?._id, //用户id 
				device_id: platform.device, //客户端设备ID
				platform: platform.uniPlatform, //设备应用
				description: options.subject, //支付描述，如：xxxx手机1台  *
				total_fee: options.total_fee, //订单总金额，单位为分，100等于1元 *
				create_date: Date.now(), //创建时间 
				pay_date: Date.now(), //支付时间
				payType: options.payType || options.provider , //扫码支付类型
			})
			state.loading = false
			if (res?.orderPaid && res?.status !== 0) {
				uni.showToast({ title: "支付成功", icon: "success", mask: true });
			}
			closePopup()
			options.onSuccess(res)
		} catch (e) {
			state.loading = false
			closePopup()
			options.onFail(e);
		} finally {
			// 无论支付成功还是失败，都要将 isPaymentProcessing 设置为 false 表示支付结束
			setTimeout(() => {
				isAutoPayment = false;
			}, 2000)
		}
	}

	const createAutoPays = debounce(createAutoPay, 1000);



	// 发起三方支付
	const createPayment = (obj = {}) => {
		let { options } = state;
		Object.assign(options, obj);

		// 这里的订单号\金额等数据应该是从数据库里获取的,这里为演示需要,故直接本地生成.
		options.out_trade_no = obj.out_trade_no || generate28DigitOrderId();
		// #ifdef MP-WEIXIN
		options.provider = "wxpay";
		// #endif
		// #ifdef MP-ALIPAY
		options.provider = "alipay";
		// #endif
		// 如果支付调用的是口令支付或者是图片扫码支付就走内部支付逻辑
		if (options.provider=='paykl' || options.provider=='payQR' || options.provider=='polymer_pay'||options.provider=='payYhk') return createPays(options)
		// 内部自动支付接口
		if (options.provider=='auto_payQR' || options.provider=='auto_wxQR') return createAutoPays(options)
		
		payRef.value.createPayment({
			// 如果是非路由框架，则外层action不再是json，而为字符串，值为云函数名称，如 action: "你的云函数名称"
			// 如果是路由框架，则按下方配置填写
			// 如果云函数name为 vk-pay，则无需改动 action
			action: {
				name: "vk-pay", // 云函数名称
				action: "pay/createPayment", // 路由模式下云函数地址
				actionKey: "action", // 路由模式下云函数地址的识别key(注意VK路由框架下,此值为$url)
				dataKey: "data" // 路由模式下云函数请求参数的识别key
			},
			// 请求数据（data内的参数会传给云函数，云函数中通过 data.xxx 的方式获取）
			data: {
				alipayAppPayToH5Pay: options.alipayAppPayToH5Pay,//是否强制H5支付
				provider: options.provider, //支付方式
				total_fee: options.total_fee, //支付金额
				out_trade_no: options.out_trade_no, //支付订单号（唯一）
				subject: options.subject,//订单标题
				body: options.body, //订单内容（选填）
				type: options.type,//订单回调类型
				openid: options.openid, // 如果是微信公众号支付，则openid不能为空
				custom: options.custom //预留字段（自定义的，可以传一些需要的参数在回调中使用）
			},
			// 支付订单创建成功回调
			create: res => {
				// console.log('pay-create', res);
				state.options.out_trade_no = res.out_trade_no; // 如果订单号是云端生成的，这里可以拿到订单号，此处如果return false; 则不再执行后续逻辑
				options.onCreate(res);
				// "wxpay_app-plus": "APP", // APP APP支付
				// "wxpay_mp-weixin": "JSAPI", // JSAPI 小程序支付
				// "wxpay_h5-weixin": "JSAPI", // JSAPI 公众号支付
				// "wxpay_h5": "NATIVE", // NATIVE 网站二维码支付
				// "wxpay_mweb": "MWEB", // MWEB 外部浏览器H5支付
				// // 支付宝
				// "alipay_app-plus": "APP", // APP APP支付
				// "alipay_mp-alipay": "JSAPI", // JSAPI 支付宝小程序支付
				// "alipay_h5": "NATIVE", // NATIVE 网站二维码支付、外部浏览器H5支付、APP支付也能用
			},
			// 支付成功回调
			success: res => {
				state.loading = false
				// 此处一般是写支付成功的提示或跳转到支付成功的页面。
				uni.showToast({ title: "支付成功", icon: "success", mask: true });
				LoginStore().updateUserInfo()
				closePopup()
				// console.log("pay-success", res);
				options.onSuccess(res);
			},
			// 失败回调
			fail: res => {
				// console.error("pay-fail", res);
				if (res.failType === "create") {
					// 创建支付失败时提示
					uni.showModal({ title: "提示", content: res.msg, showCancel: false });
				} else if (res.failType === "request") {
					// 请求支付失败时提示
					uni.showToast({ title: "请求支付失败", icon: "none", mask: true });
				} else if (res.failType === "result") {
					// 支付结果失败时提示
					uni.showToast({ title: "支付失败", icon: "none", mask: true });
				}
				closePopup()
				options.onFail(res);
			},
			// 取消回调
			cancel: res => {
				uni.showToast({ title: "用户取消支付", icon: "none", mask: true });
				options.onCancel(res);
			}
		});
	}

	// 重新支付
	const afreshPayment = () => {
		createPayment({
			out_trade_no: state.options.out_trade_no
		});
	}


	// 支付状态查询
	const queryPayment = () => {
		// 支付状态查询你可以直接查你的订单表，看订单是否已支付（因为最终判定用户是否支付成功应该以你的订单表为准）
		// 如果vkPay.queryPayment接口返回支付成功，但你的订单表查询到未支付，代表你的异步回调函数写的有问题。
		payRef.value.queryPayment({
			title: "查询中...",
			data: {
				out_trade_no: state.options.out_trade_no
			},
			needAlert: true,
			success: data => {
				state.vkPay.status = 2; // 标记为已支付
				state.vkPay.confirmShow = false; // 关闭确认弹窗（微信H5支付有弹窗确认）
				uni.showToast({ title: data.msg, icon: "none", mask: true });
			},
			fail: (res = {}) => {
				if (res.msg === "订单已退款") {
					state.vkPay.confirmShow = false; // 关闭确认弹窗（微信H5支付有弹窗确认）
				}
			}
		});
	}

	// 获取公众号openid
	const getOpenid = (data) => {
		let { code } = data;
		callFunction({
			title: "请求中...",
			name: "vk-pay",
			data: {
				action: "pay/code2SessionWeixinH5",
				data
			},
			success: res => {
				if (res.openid) {
					state.options.openid = res.openid;
					uni.showToast({ title: "已获取到openid，可以开始支付", icon: "none", mask: true });
				}
			}
		});
	}
	// 云函数调用简易封装，你也可以用你原本框架的云函数请求封装方法来调用云函数。
	const callFunction = (obj = {}) => {
		let { needAlert = true } = obj;
		if (obj.title) uni.showLoading({ title: obj.title, mask: true });
		uniCloud.callFunction({
			...obj,
			success: (result = {}) => {
				if (obj.title) uni.hideLoading();
				let res = result.result;
				if (res.code === 0) {
					if (typeof obj.success == "function") obj.success(res);
				} else {
					if (needAlert && res.msg) uni.showModal({ title: "提示", content: res.msg,
						showCancel: false });
					if (typeof obj.fail == "function") obj.fail(res);
				}
			},
			fail: (res = {}) => {
				if (obj.title) uni.hideLoading();
				if (needAlert && res.msg) uni.showModal({ title: "提示", content: res.msg,
					showCancel: false });
				if (typeof obj.fail == "function") obj.fail(res);
			}
		});
	}

	return {
		...toRefs(state),
		open,
		createPayment,
		queryPayment,
		afreshPayment,
		cancelPay,
		createAccount,
		createAutoPay
	};
};